<?php

/**
 * alltosun.com 公用函数库 common.php
 * ============================================================================
 * 版权所有 (C) 2009-2011 北京互动阳光科技有限公司，并保留所有权利。
 * 网站地址: http://www.alltosun.com
 * ----------------------------------------------------------------------------
 * 许可声明：这是一个开源程序，未经许可不得将本软件的整体或任何部分用于商业用途及再发布。
 * ============================================================================
 * $Author: 高竞竞 (gaojj@alltosun.com) $
 * $Date: 2010-12-28 下午03:21:58 $
 * $Id: common.php 26590 2013-09-29 09:17:04Z qianym $
 */

/* 在setup.php中包含
require_once MODULE_CORE.'/helper/Exception.php';
require_once MODULE_CORE.'/helper/Rule.php';
require_once MODULE_CORE.'/helper/Router.php';
require_once MODULE_CORE.'/helper/Url.php';
require_once MODULE_CORE.'/helper/Module.php';
require_once MODULE_CORE.'/helper/Acl.php';
require_once MODULE_CORE.'/helper/Message.php';
require_once MODULE_CORE.'/helper/Form.php';
require_once MODULE_CORE.'/helper/Filter.php';
require_once MODULE_CORE.'/helper/smarty.php';
*/

/**
 * utf-8编码下截取中英文混合输入字符串长度，
 * 注意：
 *     1，一个长度  = 两个英文字符（如“dr”） = 一个汉字（如“宁”）
 *     2，只能截取utf-8编码的字符，在传入字符串时请先转换编码
 * @param  string $str 传入字符串
 * @param  int $start 起始位置
 * @param  int $length 截取长度
 * @return string
 *
 * @example substr_utf8('dreamwing', 0, 3) // dreamw
 * @example substr_utf8('宁海新', 1, 2)    // 海新
 * @example substr_utf8('宁海新', 1, 3)    // 海新
 * @example substr_utf8('宁海新', 0, 3)    // 宁海新
 * @example substr_utf8('de的w人ww', 0, 3) // de的w
 */
function substr_utf8($str, $start, $length) {
    if (!trim($str)) {
        return '';
    }
    $chars = $str;
    // $i 字符串数组中的键、$n 非英文字符长度、$m纯英文字符长度
    $i = $m = $n = 0;
    $str_length = strlen($str);
    for ($i; $i < $str_length; $i++) {
        if (preg_match('/[0-9a-zA-Z]/', $chars{$i})) {
            //纯英文，占两个byte
            $m++;
        } else {
            //非英文字节,占3个byte
            $n++;
        }
        $k = $n / 3 + $m / 2;
        if ($k >= $length) {
            break;
        }
    }

    // 实际截取的长度
    $l = $n / 3 + $m;
    // mb_substr不会出现乱码
    return mb_substr($str, $start, $l, 'utf-8');
}

function cut_str($str, $len, $fix = '') {
    if (strlen($str) <= $len) {
        return $str;
    }

    $return_str = '';
    $i = 0;
    $n = 0;
    while (($n < $len) && ($i <= strlen($str))) {
        $temp_str = substr($str, $i, 1);
        $ascnum = ord($temp_str);//得到字符串中第$i位字符的ascii码

        //如果ASCII位高与224，
        if ($ascnum >= 224) {
            $return_str .= substr($str, $i, 3); //根据UTF-8编码规范，将3个连续的字符计为单个字符
            $i += 3; //实际Byte计为3
            $n++; //字串长度计1

            //如果ASCII位高与192，
        } elseif ($ascnum >= 192) {
            $return_str .= substr($str, $i, 2); //根据UTF-8编码规范，将2个连续的字符计为单个字符
            $i += 2; //实际Byte计为2
            $n++; //字串长度计1

            // 如果是大写字母，
        } elseif ($ascnum >= 65 && $ascnum <= 90) {
            $return_str .= substr($str, $i, 1);
            $i++; //实际的Byte数仍计1个
            $n++; //但考虑整体美观，大写字母计成一个高位字符

            // 其他情况下，包括小写字母和半角标点符号，
        } else {
            $return_str .= substr($str, $i, 1);
            $i++; //实际的Byte数计1个
            $n += 0.5; //小写字母和半角标点等与半个高位字符宽...
        }
    }

    // 因为在是sbu_arrstr中调的此方法，已级补$fix了，此处先注释掉
    if ($fix && strlen($return_str) != strlen($str)) {
        $return_str .= $fix;
    }

    return $return_str;
}

/**
 * size的换算
 * @param $number
 * @return string
 */
function conversion($number) {
    $num = strlen($number);
    if ($num > 9) {
        $num = $num - 9;
        return substr($number, 0, $num) . "GB";
    } elseif ($num > 6) {
        $num = $num - 6;
        return substr($number, 0, $num) . "MB";
    } elseif ($num > 3) {
        $num = $num - 3;
        return substr($number, 0, $num) . "KB";
    } else {
        return $number . "B";
    }
}

/**
 * 二维数组按照子级数组中指定的某个值进行排序
 * @param array $list 二维数组
 * @param string $order_key 指定的某个值
 * @return array
 */
function arraySortByKey($list, $order_key) {
    $tmp = array();
    foreach ($list as &$ma) {
        $tmp[] = &$ma[$order_key];
    }
    array_multisort($tmp, $list);

    return $list;
}

/*
# 函数功能：计算身份证号码中的检校码
# 函数名称：idcard_verify_number
# 参数表 ：string $idcard_base 身份证号码的前十七位
# 返回值 ：string 检校码
# 更新时间：Fri Mar 28 09:50:19 CST 2008
*/
function idcard_verify_number($idcard_base) {
    if (strlen($idcard_base) != 17) {
        return false;
    }
    $factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //debug 加权因子
    $verify_number_list = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); //debug 校验码对应值
    $checksum = 0;
    for ($i = 0; $i < strlen($idcard_base); $i++) {
        $checksum += substr($idcard_base, $i, 1) * $factor[$i];
    }
    $mod = $checksum % 11;
    $verify_number = $verify_number_list[$mod];
    return $verify_number;
}

/*
# 函数功能：将15位身份证升级到18位
# 函数名称：idcard_15to18
# 参数表 ：string $idcard 十五位身份证号码
# 返回值 ：string
# 更新时间：Fri Mar 28 09:49:13 CST 2008
*/
function idcard_15to18($idcard) {
    if (strlen($idcard) != 15) {
        return false;
    } else {// 如果身份证顺序码是996 997 998 999，这些是为百岁以上老人的特殊编码
        if (array_search(substr($idcard, 12, 3), array('996', '997', '998', '999')) !== false) {
            $idcard = substr($idcard, 0, 6) . '18' . substr($idcard, 6, 15);
        } else {
            $idcard = substr($idcard, 0, 6) . '19' . substr($idcard, 6, 15);
        }
    }
    $idcard = $idcard . idcard_verify_number($idcard);
    return $idcard;
}

/*
# 函数功能：18位身份证校验码有效性检查
# 函数名称：idcard_checksum18
# 参数表 ：string $idcard 十八位身份证号码
# 返回值 ：bool
# 更新时间：Fri Mar 28 09:48:36 CST 2008
*/
function idcard_checksum18($idcard) {
    if (strlen($idcard) != 18) {
        return false;
    }
    $idcard_base = substr($idcard, 0, 17);
    if (idcard_verify_number($idcard_base) != strtoupper(substr($idcard, 17, 1))) {
        return false;
    } else {
        return true;
    }
}

/*
# 函数功能：身份证号码检查接口函数
# 函数名称：check_id
# 参数表 ：string $idcard 身份证号码
# 返回值 ：bool 是否正确
# 更新时间：Fri Mar 28 09:47:43 CST 2008
*/
function check_card_id($idcard) {
    if (strlen($idcard) == 15 || strlen($idcard) == 18) {
        if (strlen($idcard) == 15) {
            $idcard = idcard_15to18($idcard);
        }
        if (idcard_checksum18($idcard)) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

/**
 * 按path排序数据库数据
 * @param array $list 要排序的数组
 * @param string $field path字段名称
 * @param string $separator 分隔符
 * @return array
 * array(7) {
 * ["id"]=>
 * int(5)
 * ["title"]=>
 * string(4) "five"
 * ["parent_id"]=>
 * int(3)
 * ["path"]=>
 * string(7) "0-1-3-5"
 * ["path_level"]=>
 * int(3)
 * ["children_ids"]=>
 * array(0) {
 * }
 * ["has_child"]=>
 * bool(false)
 * }
 */
function arraySortByPath($list, $field = 'path', $separator = '-') {
    $sort_arr = array();
    //$parent_ids = array();
    $childrens = array();

    foreach ($list as $k => $v) {
        $arr = explode($separator, $v[$field]);
        $count = count($arr);

        $path = $v[$field] . '-' . $v['id'];

        $sort_arr[] = $path;
        $list[$k][$field] = $path;
        $list[$k]['path_level'] = $count;

        /*
        //父id数组，用于下次循环判断是否有子级
        if ($v['parent_id'] > 0) {
            $parent_ids[] = $v['parent_id'];
        }
        */

        //子
        if ($count > 1) {
            for ($i = 1; $i < $count; $i++) {
                $pid = $arr[$i];

                if (!isset($childrens[$pid])) {
                    $childrens[$pid] = array();
                }

                if (isset($arr[$i + 1])) {
                    $childrens[$pid][] = intval($arr[$i + 1]['id']);
                } else {
                    $childrens[$pid][] = $v['id'];
                }

            }
        }
    }

    //$childrens  = array_unique($childrens);
    //$parent_ids = array_unique($parent_ids);

    foreach ($list as $k => $v) {
        $list[$k]['children_ids'] = array();
        $list[$k]['has_child'] = false;

        if (isset($childrens) && !empty($childrens[$v['id']])) {
            $childrens[$v['id']] = array_unique($childrens[$v['id']]);
            $list[$k]['children_ids'] = $childrens[$v['id']];
            $list[$k]['has_child'] = true;
        }

    }

    array_multisort($sort_arr, $list);

    return $list;
}


/**
 * 验证文件上传状态
 * @param array $file_info 上传的文件信息，$_FILES['name']
 * @param int $max_size 图片大小
 * @param $type 类型 0:图片; 1:附件
 * @return string 错误信息failed_msg
 * @author gaojj@alltosun.com
 */
function check_upload($file_info = NULL, $max_size = 0, $type = 0) {
    if (!isset($file_info)) {
        return '没有找到上传的文件';
    }
    if (isset($file_info['error']) && $file_info['error'] != 0) {
        $error_mapping = array(
            0 => "上传成功！",
            1 => "服务器限制的上传文件大小为" . ini_get('upload_max_filesize'),
            2 => "上传文件大小超过了表单中MAX_FILE_SIZE的限制！",
            3 => "只有部分文件被上传了，请重试！",
            4 => "没有选择要上传的文件。",
            6 => "服务器上传临时目录不存在，请联系系统管理员。",
            7 => "文件无法写入磁盘，请联系系统管理员。",
            8 => "某个PHP扩展导致上传失败，请联系系统管理员。"
        );

        $error_id = $file_info['error'];

        return '上传失败，' . $error_mapping[$error_id];
    }

    if (empty($file_info['size'])) {
        return '选中的文件大小为空';
    }

    if ($type == 1) {
        $allow_max_size = $max_size ? $max_size : Config::get('attachment_max_size');
        $allow_type = Config::get('allow_type');
    } else {
        $allow_max_size = $max_size ? $max_size : Config::get('image_max_size');
        $allow_type = Config::get('allow_image_type');
    }

    $file_extension_name = pathinfo($file_info['name'], PATHINFO_EXTENSION);
    if (strtolower($file_extension_name) == 'php') {
        return '不允许的上传类型';
    }
    /*if (!in_array(strtolower($file_extension_name), $allow_type)) {
        $name = json_encode($file_info['name']);
        $ext = json_encode($file_extension_name);
        $all_type = json_encode($allow_type);

        //return '上传文件的类型不允许'.$ext.'11'.$name.'##'.$all_type;
    }*/
    if ($allow_max_size && $file_info['size'] > $allow_max_size) {
        return '上传文件的大小不得超过' . conversion($allow_max_size);
    }

    if (empty($file_info['name'])) {
        return '选中的文件没有文件名';
    }

    if (empty($file_info['tmp_name'])) {
        return '上传到服务器临时目录失败';
    }

    return '';
}

/**
 * 验证多文件上传状态（以path[]数组形式作为file的name上传的文件组）
 * @param $file_info 上传的文件信息，$_FILES['name']
 * @return array 对应索引的错误信息数组array(0=>'failed_msg')
 * @author gaojj@alltosun.com
 */
function check_multiple_upload($files_info, $max_size = 0, $type = 0) {
    $failed_msg_arr = array();
    foreach ($files_info['name'] as $k => $v) {
        if (empty($v)) {
            continue;
        }

        $file_info = array(
            'name' => $files_info['name'][$k],
            'tmp_name' => $files_info['tmp_name'][$k],
            'size' => $files_info['size'][$k],
            'type' => $files_info['type'][$k],
            'error' => $files_info['error'][$k]
        );

        $failed_msg = check_upload($file_info, $max_size = 0, $type = 0);
        if (!empty($failed_msg)) {
            $failed_msg_arr[$k] = '第' . ($k + 1) . '个文件上传失败：' . $failed_msg;
        }
    }
    return $failed_msg_arr;
}

// 上传文件
function an_upload($file, $ext = 'jpg') {
    $time = time();
    $folder = UPLOAD_PATH . date('/Y/m/d', $time);

    if (!file_exists($folder) && !@mkdir($folder, 0777, true)) {
        return '';
    }

    $allow_image_type = Config::get('allow_image_type');
    // 如果是图片的话，则按当前时间+文件大小+随机数（用于区分同一秒多个进程上传不同文件）存放文件
    // 这样可以让不同模型使用同一张图片可以生成不同缩略图

    if (in_array(strtolower($ext), $allow_image_type)) {
        static $count = 1;

        // u为microseconds，> PHP 5.2.2
        if (version_compare(PHP_VERSION, '5.2.2') >= 0) {
            $current_time = date('YmdHisu', $time);
        } else {
            $current_time = date('YmdHis', $time);
        }

        $random = mt_rand(0, 100);

        $target = $folder . '/' . $current_time . '_' . $count . '_' . filesize($file) . '_' . $random . '.' . $ext;

        $count++;
    } else {
        // 同一文件只上传一次
        $target = $folder . '/' . md5_file($file) . filesize($file) . '.' . $ext;
    }
    $target = trim($target, '.');
    /* if ($this->user_id == 16) {
        var_dump($ext, $target);
        exit;
    } */

    if (!file_exists($target)) {
        if (!rename($file, $target)) {
            return '';
        }
    }

    return substr($target, strlen(UPLOAD_PATH));
}

/**
 * 后台访问权限验证
 * @param string $controller
 * @param string $action
 * @author gaojj@alltosun.com
 * @return bool
 */
function check_auth($controller, $action, $res_name) {
    // 未登录，返回FALSE
    $admin_id = user_helper::get_admin_id();
    if (empty($admin_id)) {
        return FALSE;
    }
    $role_id = _uri('user', $admin_id, 'role_id');
    $privilege = _uri('user_role', $role_id, 'privilege');

    // 没有权限，返回FALSE
    if (empty($privilege)) {
        return FALSE;
    }

    // 拥有所有权限，返回TRUE
    if ($privilege == '*') {
        return TRUE;
    }

    $privileges = explode(',', $privilege);

    if ($controller == 'article' &&
        in_array($action, array('add', 'save', 'push', 'unpush', 'del')) &&
        $res_name == 'news'
    ) {
        // 文章投稿特例
        $contribute_menu_id = _uri('admin_menu', array(
            'controller' => 'article',
            'action' => 'contribute',
            'res_name' => 'contribute'
        ), 'id');
        if (in_array($contribute_menu_id, $privileges)) {
            return TRUE;
        }
    } elseif ($controller == 'res_relation') {
        // 关联信息特例
        return TRUE;
    }

    $menu_ids = array();
    // 获取具体资源的所有操作权限id
    $menu_ids[] = _uri('admin_menu', array('controller' => $controller, 'action' => '', 'res_name' => $res_name), 'id');
    // 获取整个控制器的所有操作权限id
    $menu_ids[] = _uri('admin_menu', array('controller' => $controller, 'action' => '', 'res_name' => ''), 'id');
    // 获取具体资源的具体操作权限id
    $menu_ids[] = _uri('admin_menu', array(
        'controller' => $controller,
        'action' => $action,
        'res_name' => $res_name
    ), 'id');
    // 获取整个控制器的具体操作权限id
    $menu_ids[] = _uri('admin_menu', array('controller' => $controller, 'action' => $action, 'res_name' => ''), 'id');

    if (!array_intersect($menu_ids, $privileges)) {
        $menu_res_name = _uri('admin_menu', array('controller' => $controller), 'res_name');
        if ($menu_res_name && $menu_res_name != $res_name) {
            throw new Exception('菜单中设置了res_name，请POST或者GET传入res_name');
        }
        return FALSE;
    }

    return TRUE;
}

/**
 * 通过url返回企业id
 * @param string $string 企业名称
 * @return int 企业id
 */
function get_company_id_by_url($string = '') {
    if (is_numeric($string)) {
        $company_id = intval($string);
        $company_info = _uri('company', $company_id);
    } else {
        $company_info = _uri('company', array('domain' => $string));
    }

    if (!$company_info || $company_info['status'] != 1) {
        return 0;
    }

    return $company_info['id'];
}

//获取当前url(包含所有参数)
function get_url() {
    return HTTP_PROTOCOL . $_SERVER ['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}

/**
 * 显示星期几
 * @param int $time
 * @return string
 */
function time_week($time) {
    $arr = array('天', '一', '二', '三', '四', '五', '六');

    return '星期' . $arr[date('w', strtotime($time))];
}

/**
 * 时间格式化
 * @param int $time
 * @param string $format
 * @return string
 */
function time_format($time, $format = "Y-m-d H:i") {
    $tmp_time = strtotime($time);
    if ($tmp_time < strtotime('2038-12-31')) {
        return date($format, $tmp_time);
    } else {
        return date_format(date_create($time), $format);
    }

}

/**
 * 显示距离当前时间的字符串
 * @param $time int 时间戳
 * @return string
 * @author gaojj@alltosun.com
 */
function time_past($time) {
    $now = time();
    $time_past = $now - strtotime($time);

    // 如果小于1分钟（60s），则显示"刚刚"
    if ($time_past < 60) {
        return '刚刚';
    }

    $time_mapping = array(
        '分钟' => '60',
        '小时' => '24',
        '天' => '7',
        '周' => '4',
        '月' => '12',
        '年' => '100'
    );

    $time_past = floor($time_past / 60);

    foreach ($time_mapping as $k => $v) {
        if ($time_past < $v) {
            return floor($time_past) . $k . '前';
        }
        $time_past = $time_past / $v;
    }

    // 如果小于1小时（60*60s），则显示N分钟前
    // 如果小于24个小时（60*60*24s），则显示N小时前
    // 如果大于24个小时（60*60*24s），则显示N天前
}

/**
 * 显示距离当前时间的字符串
 * @param $time int 时间戳
 * @return string
 * @author gaojj@alltosun.com
 */
function time_pasted($time) {
    $now = time();
    $time_past = $now - strtotime($time);

    // 如果小于1分钟（60s），则显示"刚刚"
    if ($time_past < 60) {
        return $time_past . ' 秒';
    }

    $time_mapping = array(
        ' 分钟' => '60',
        ' 小时' => '24',
        ' 天' => '7',
        ' 周' => '4',
        ' 月' => '12',
        ' 年' => '100'
    );

    $time_past = floor($time_past / 60);

    foreach ($time_mapping as $k => $v) {
        if ($time_past < $v) {
            return floor($time_past) . $k;
        }
        $time_past = $time_past / $v;
    }

    // 如果小于1小时（60*60s），则显示N分钟
    // 如果小于24个小时（60*60*24s），则显示N小时
    // 如果大于24个小时（60*60*24s），则显示N天
}

/**
 * 显示当前时间离指定时间还剩余多少天
 * @param unknown_type $time
 * @return string
 */
function time_left($time, $start_time = null) {
    $now = time();
    if ($start_time && strtotime($start_time) > $now) {
        return '尚未开始';
    }

    $time_left = strtotime($time) - $now;

    $has_left = 1;
    $pre = '余';
    if ($time_left < 0) {
        $has_left = 0;
        $pre = '超';
        $time_left = -$time_left;
    }

    $day = 60 * 60 * 24;

    // 如果小于1分钟（60s），则显示"刚刚"
    if ($time_left < 60) {
        return '不到1秒';
    }

    if ($time_left > $day) {
        $time_left = $time_left / $day;
        $strings = $pre;
        $time_day = floor($time_left);
        if ($time_day > 0) {
            $strings .= $time_day . '天';
        }

        //时
        $time_left = ($time_left - $time_day) * 24;
        $time_hour = floor($time_left);
        if ($time_hour > 0) {
            $strings .= $time_hour . '小时';
        }

        //分
        $time_left = ($time_left - $time_hour) * 60;
        $time_minute = floor($time_left);
        if ($time_minute > 0) {
            $strings .= $time_minute . '分';
        }

        return $strings;
    }

    $time_mapping = array(
        '分钟' => '60',
        '小时' => '24'
    );

    $time_left = floor($time_left / 60);

    foreach ($time_mapping as $k => $v) {
        if ($time_left < $v) {
            if ($k == '小时') {
                $hours = floor($time_left);
                $minute = floor(($time_left - $hours) * 60);
                return $pre . $hours . $k . $minute . '分';
            }
            return $pre . floor($time_left) . $k;
        }
        $time_left = $time_left / $v;
    }
}

/**
 * 从resource表中获取资源对应的表名，如果不存在，返回类名
 * @author anr@alltosun.com
 * @param string ,int $res_name
 * @return string 表名或类名
 */
function get_res_table($res_name) {
    $tem = get_resource($res_name, 'table');
    if (!empty($tem)) {
        return $res_name;
    }
    return $tem;
}

/**
 * 获取seo信息 根据url取相应的SEO信息
 * 返回有问题
 * @param string $field title\description\keywords
 * @return array('title'=>**, 'description'=>'**', 'keywords'=>**);
 * @author anr@alltosun.com
 */
function get_seo($field) {
    if (empty($field)) {
        return '';
    }

    $url = Request::Get('url', '');
    $url = trim($url, '/');
    list($url) = explode('.', $url);
    $params = explode('/', $url);

    static $seo_arr = array();

    if (isset($seo_arr[$field])) {
        return $seo_arr[$field];
    }

    // 获取网站的整体title,keywords,description
    $seo_arr['title'] = _uri('setting', array('field' => 'title'), 'value');
    $seo_arr['keywords'] = _uri('setting', array('field' => 'title'), 'value');
    $seo_arr['description'] = _uri('setting', array('field' => 'description'), 'value');

    if (isset($params[0])) {
        // 如果1级频道
        // /article/
        $name = $params[0];
        $res = get_resource($name);

        if (!empty($res)) {
            $seo_arr['title'] = $res['description'] . ' - ' . $seo_arr['title'];
        }
    }
    if (isset($params[1]) && $params[1] = intval($params[1])) {
        // 如果是终极页
        // /article/748.html
        // 排除单页 /overview/organization.html
        if ($params[0] == 'memorial') {
            return $seo_arr[$field];
        }
        $tem_arr = _uri($params[0], $params[1]);
        if (!empty($tem_arr['title'])) {
            // article 为 title
            $seo_arr['title'] = $tem_arr['title'] . ' - ' . $seo_arr['title'];
        } else {
            // 产品为 name
            $seo_arr['title'] = $tem_arr['name'] . ' - ' . $seo_arr['title'];
        }
    }
    if (isset($params[2]) && ($params[2] = intval($params[2])) && in_array('category', $params)) {
        // $level == 3
        // 如果是2级栏目
        // /article/category/363.html
        // var_dump($params);
        $seo_arr['title'] = _uri('category', $params[2], 'name') . ' - ' . $seo_arr['title'];
    }

    //if (in_array($k, array('title', 'keywords', 'description'))) return $seo_arr;
    return $seo_arr[$field];
}

/**
 * 换行转换
 * @param string $str
 * @param string $replace 将换行转成字符
 * @return string
 * @author gaojj@alltosun.com
 */
function strip_br($str, $replace = '') {
    if (is_array($str)) {
        foreach ($str as $k => $v) {
            $str[$k] = strip_br($v, $replace);
        }
        return $str;
    } else {
        $order = array("\r\n", "\n", "\r");
        return str_replace($order, $replace, $str);
    }
}


/**
 * 获取群组资源的url
 * @param string $type 访问的群组资源类型
 * @param int $id 访问的资源id
 * @return string
 * @author gaojj@alltosun.com
 * @TODO 自定义blog域名
 * @TODO 自定义group地址
 * @TODO 扩展到获取所有资源的url
 * @example {$group_id|group_url}群组首页；
 * @example {'mine'|group_url}我的群组首页；
 * @example {'all'|group_url}所有群组列表
 * @example {'member'|group_url:$group_id}群组成员列表
 * @example {'article'|group_url:$article_id}群组话题详情
 * @example {'article_list'|group_url:$group_id}群组话题列表
 */
function group_url($type = '', $id = 0) {
    // 群组首页
    if (is_numeric($type)) {
        $id = $type;
        return "/blog/group/$id.html";
    }

    if (empty($type)) {
        return '/blog/group.html';
    }

    if (empty($id)) {
        return "/blog/group/$type.html";
    }

    // 群组成员
    if ($type == 'member') {
        return "/blog/group/$id/$type.html";
    }

    // 群组文章
    if ($type == 'article') {
        return "/blog/group/$type/$id.html";
    }
}

/**
 * 获取资源首页、列表页、详情页的url
 * @param int|string $res_name 资源类型/资源名称
 * @param int|string $res_id 资源id/自定义名称
 * @return string
 * @deprecated
 */
function res_url($res_name, $res_id = 0) {
    return AnUrl($res_name, $res_id);
}

/**
 * 获取符合系统设置的资源url地址
 * @param int|string $res_name 资源类型/资源名称
 * @param int|string $res_id 资源id/自定义名称
 * @example 获取资源首页：AnUrl('product')，结果为res_name.html
 * @example 获取资源列表页：AnUrl('category', 1)，结果为res_name/category.html
 * @example 获取资源详情页：AnUrl('product', 1)，结果为product/1.html(格式为res_name/res_id.html)
 *                           如果该资源在url表中有自定义url，则结果为res_name/custom_url.html
 * @example 其他使用方式：AnUrl('product/add')，结果为product/add.html
 *                         AnUrl('product/edit?id=1')，结果为product/edit.html?id=1
 * @return string
 */
function AnUrl($res_name = '', $res_id = 0) {
    if (is_numeric($res_name)) {
        $res_name = get_resource($res_name, 'name');
    }

    // 拼装企业domain
    $domain = '';
    $user_id = user_helper::get_user_id();
    if ($user_id) {
        $company_id = user_helper::get_user_company_id();
    } else {
        $company_id = Cookie::get('remember_company');
    }

    if ($company_id && (int)$company_id == $company_id) {
        //$domain = _uri('company', $company_id, 'domain');
    }
    //an_dump(SITE_URL);
    if (!$res_name) {
        if ($domain) {
            return SITE_URL . '/' . $domain;
        } else {
            return SITE_URL;
        }
    }

    $location_hash = $query_string = '';
    if (strpos($res_name, '#') !== FALSE) {
        // location_hash
        list($res_name, $location_hash) = explode('#', $res_name);
    }
    if (strpos($res_name, '?') !== FALSE) {
        // query string
        list($res_name, $query_string) = explode('?', $res_name);
    }

    $url = $url_res = '';
    if (strncasecmp($res_name, 'http://', 7) != 0) {
        $url = SITE_URL;
    }

    // url rewrite on
    $url .= Config::get('rewrite_on') ? '/' : '/index.php?url=';
    if ($domain) {
        $url .= $domain . '/';
    }

    $url_res = $res_name;

    $url .= trim($url_res, '/');

    // 具体的某一资源
    if ($res_id) {
        $url .= "/$res_id";
    }
    //an_dump($url.'11');
    // html static on
    if (Config::get('html_static')) {
        $url .= '.html';
    }

    if (!empty($query_string)) {
        $connector = strpos($url, '?') !== FALSE ? '&' : '?';
        $url .= $connector . $query_string;
    }
    //an_dump($url.'55');
    if (!empty($location_hash)) {
        $url .= '#' . $location_hash;
    }
    //an_dump($url, '66');

    return $url;
}

/**
 * 转换时间为固定格式,如果为当天则显示时间(15:00),否则显示日期(12月01日)
 * @param $date (2010-06-22 16:00:00)
 * @param $sep 月和日之间的分割('-', '.', ...)
 * @return string
 * @author gaojj@alltosun.com
 */
function track_date($date, $sep = '') {
    //获取当前时间
    $now = date('Y-m-d');
    //获取要转换的时间
    list($date, $time) = explode(' ', $date);

    if ($now == $date) {
        return substr($time, 0, 5);
    } else {
        list($y, $m, $d) = explode('-', $date);
        if ($sep) {
            return $m . $sep . $d;
        } else {
            return $m . '月' . $d . '日';
        }

    }
}

/**
 * 将多行的字符串转换为数组（暂未用到，可以用于自定义属性默认值的处理）
 * @param string $line
 * @author gaojj@alltosun.com
 */
function line_to_array($line) {
    return explode("\n", str_replace(array("\r\n", "\r"), "\n", $line));
}

/**
 * 模板中的select
 * @param $array array 二维数组
 * @param string 显示的字段名称
 * @return array 一维数组
 * @author ninghx@alltosun.com
 */
function array_to_option($array, $val = 'title') {
    $result = array();
    if (empty($array)) {
        return $result;
    }
    foreach ($array as $v) {
        if ($v) {
            $result[$v['id']] = $v[$val];
        }
    }
    return $result;
}

/**
 * 获取系统配置信息
 * @param string $field
 * @return string
 * @author gaojj@alltosun.com
 */
function setting_info($field) {
    $option = array('field' => $field);
    return _uri('setting', $option, 'value');
}

/**
 * 多字节的字符串反序列化（比如原先是gbk的数据序列化后，在utf-8的环境下反序列化）
 * @param $serial_str
 *
 */
function mb_unserialize($serial_str) {
    $out = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $serial_str);
    return unserialize($out);
}

if (!function_exists('_')) {
    /**
     * 多国语言方法
     * @param string $lang
     * @TODO
     */
    function _($lang) {
        // 测试用
        $lang_mapping = array(
            'blog' => '日志',
            'media' => '博客视频',
            'article' => '资讯',
            'photo' => '照片',
            'product' => '产品'
        );
        $action_lang_mapping = array(
            'add' => '添加',
            'edit' => '编辑',
            'delete' => '删除',
            'save' => '保存'
        );
        $goods_lang_mapping = array(
            'goods' => '商品',
            'bag' => '礼包',
            'preorder' => '预定墓位',
            'tomb' => '购买墓位',
            'car' => '派车'
        );
        $lang_mapping += $action_lang_mapping;
        $lang_mapping += $goods_lang_mapping;

        return isset($lang_mapping[$lang]) ? $lang_mapping[$lang] : $lang;
    }
}

/**
 * 自定义error_handler
 * @param int $errno
 * @param str $errstr
 * @param str $errfile
 * @param str $errline
 */
function an_error_handler($errno, $errstr, $errfile, $errline) {
    if (stripos($errstr, 'memcache') !== FALSE) {
        $log = "Error$errno:$errstr in $errfile on $errline";
        $debug = debug_backtrace();
        $log .= var_export($debug, TRUE);
        error_log($log, 1, 'root@alltosun.com');
    }
    return FALSE;
}

/**
 * PHP 清除HTML代码、空格、回车换行符的函数
 * @author liww@alltosun.com
 */
function strip_space($str) {
    $str = str_ireplace(array("\t", "\r\n", "\r", "\n", " ", "&nbsp;"), "", $str);
    return trim($str);
}

/**
 * 去除空行
 * @param $str
 * @author gaojj@alltosun.com
 */
function strip_empty_lines($str) {
    while (stripos($str, '<br><br>') !== FALSE || stripos($str, '<br /><br />') !== FALSE) {
        $str = str_ireplace(array('<br><br>', '<br /><br />'), '<br>', $str);
    }
    return $str;
}

/**
 * 对数组的所有key, value进行编码转换
 * @param string $in_charset
 * @param string $out_charset
 * @param string|array $array
 * @return string|array
 */
function iconv_array($in_charset, $out_charset, $array) {
    if (is_array($array)) {
        foreach ($array as $k => $v) {
            $k = iconv($in_charset, $out_charset, $k);
            $array[$k] = iconv_array($in_charset, $out_charset, $v);
        }
    } else {
        $array = iconv($in_charset, $out_charset, $array);
    }

    return $array;
}

/*
 * 根据给定的资源名和资源id获取它的title，当获取到时，返回title，没有获取则返回FALSE
 * @param $res_name
 * @param $res_id
 */
function display_title($res_name, $res_id, $title = 'title') {
    if (empty($res_id) || empty($res_name)) {
        return '';
    }

    return _uri($res_name, $res_id, $title);
}

/**
 * 更改某资源的相关字段
 * @param string $res_name
 * @param int $res_id
 * @param array $info
 * @return boolean
 */
function update_res_field($res_name, $res_id, $info) {
    if (empty($res_id) || empty($res_name) || !is_array($info)) {
        return FALSE;
    }

    $res_info = _uri($res_name, $res_id);
    if (empty($res_info)) {
        return FALSE;
    }

    foreach ($info as $k => $v) {
        if (!array_key_exists($k, $res_info)) {
            return FALSE;
        }

        if (!is_numeric($v)) {
            $info[$k] = AnFilter::filter_string($v);
        }
    }

    return _model($res_name)->update($res_id, $info);
}

/**
 * 取得某资源的信息
 * @param string $res_name
 * @param int $res_id
 * @return array
 */
function get_res_info($res_name, $res_id, $is_strict = 0) {
    if (empty($res_name) || empty($res_id)) {
        return array();
    }

    $res_info = _uri(AnFilter::filter_string($res_name), (int)$res_id);
    if (empty($res_info) || ($is_strict == 1 && $res_info['status'] != 1)) {
        return array();
    }

    return $res_info;
}

/*
 *根据给定的资源名称和资源id判断给定用户对此资源是否有操作权限。
 *@param $res_name
 *@param $res_id
 *@param $user_id
 *@param $staff_type 如果传1，则员工可以操作，传0，则员工不能操作, 默认为0
 *@param $login_type 如果传1，则需要登录才能进行此操作，传0，则不需登录也能进行此操作，默认为1
 *return TRUE or FALSE
 *@author zhangtao
 */
function check_auth_for_res($res_name, $res_id, $user_id, $staff_type = 0, $login_type = 1) {
    if ($res_name && $res_id && $user_id) {
        if (user_helper::is_admin($user_id)) {
            return TRUE;
        }
        $res_user_id = _uri($res_name, $res_id);
        if ($res_user_id && isset($res_user_id['user_id'])) {
            if ($login_type && !user_helper::get_user_id()) {
                return FALSE;
            }
            if ($staff_type && user_helper::is_staff($user_id)) {
                return TRUE;
            }
            if ($res_user_id['user_id'] == $user_id) {
                return TRUE;
            }
        }
    } else {
        return FALSE;
    }
}

/**
 * 敏感词过滤
 * @param string $subject 原字符串
 * @param string $separator 分隔符 默认空格
 * @param string $replace 替换字符串 无->不允许发布带有敏感词的微博
 */
function filter_words($subject, $separator = ' ', $replace = '') {
    // 获取关键词 从setting表
    $filter_words = _uri('setting', array('field' => 'filter_words'), 'value');
    // $filter_words = Config::get('filter_words');

    if (!$filter_words) {
        return $subject;
    }

    $filter_arr = explode($separator, $filter_words);

    $subject_replace = str_replace($filter_arr, $replace, $subject);

    if ($replace) {
        return $subject_replace;
    }

    $cmp = strcmp($subject, $subject_replace);

    if ($cmp == 0) {
        return $subject;
    }

    return '您发表的内容中含有不良词语！';
}

/**
 * 框架执行时间，微秒
 * @return float 执行时间
 */
function run_time() {
    return microtime(TRUE) - START_TIME;
}

/**
 * 文本框里的文本转化成html
 * @param string $str
 * @return str
 */
function text_to_html($str) {
    $order = array("\r\n", "\n", "\r");
    $str = str_replace($order, '<br/>', $str);
    $str = str_replace(" ", "&nbsp;", $str);

    return $str;
}


/**
 * 打印信息
 */
function an_dump() {
    $arr = func_get_args();

    echo '<pre>';
    foreach ($arr as $v) {
        var_dump($v);
    }
    echo '</pre>';
}


/**
 * create操作时的log添加
 * @param array $info
 */
function write_create_log($info = array()) {
    if (isset($info[0]) && isset($info[1])) {
        _widget('log')->record($info[0], $info[1], 'create');
    }
}

/**
 * update之前操作时的log添加
 * @param array $info
 */
function write_updateBEF_log($info = array()) {
    if (isset($info[0]) && isset($info[1])) {
        _widget('log')->record($info[0], $info[1], 'updateBEF');
    }
}

/**
 * update之前操作时的log添加
 * @param array $info
 */
function write_update_log($info = array()) {
    if (isset($info[0]) && isset($info[1])) {
        _widget('log')->record($info[0], $info[1], 'update');
    }
}

/**
 * delete操作时的log添加
 * @param array $info
 */
function write_delete_log($info = array()) {
    if (isset($info[0]) && isset($info[1])) {
        _widget('log')->record($info[0], $info[1], 'delete');
    }
}

//test pinyin

function Pinyin($_String, $_Code = 'UTF8') { //GBK页面可改为gb2312，其他随意填写为UTF8
    $_DataKey = "a|ai|an|ang|ao|ba|bai|ban|bang|bao|bei|ben|beng|bi|bian|biao|bie|bin|bing|bo|bu|ca|cai|can|cang|cao|ce|ceng|cha" .
                "|chai|chan|chang|chao|che|chen|cheng|chi|chong|chou|chu|chuai|chuan|chuang|chui|chun|chuo|ci|cong|cou|cu|" .
                "cuan|cui|cun|cuo|da|dai|dan|dang|dao|de|deng|di|dian|diao|die|ding|diu|dong|dou|du|duan|dui|dun|duo|e|en|er" .
                "|fa|fan|fang|fei|fen|feng|fo|fou|fu|ga|gai|gan|gang|gao|ge|gei|gen|geng|gong|gou|gu|gua|guai|guan|guang|gui" .
                "|gun|guo|ha|hai|han|hang|hao|he|hei|hen|heng|hong|hou|hu|hua|huai|huan|huang|hui|hun|huo|ji|jia|jian|jiang" .
                "|jiao|jie|jin|jing|jiong|jiu|ju|juan|jue|jun|ka|kai|kan|kang|kao|ke|ken|keng|kong|kou|ku|kua|kuai|kuan|kuang" .
                "|kui|kun|kuo|la|lai|lan|lang|lao|le|lei|leng|li|lia|lian|liang|liao|lie|lin|ling|liu|long|lou|lu|lv|luan|lue" .
                "|lun|luo|ma|mai|man|mang|mao|me|mei|men|meng|mi|mian|miao|mie|min|ming|miu|mo|mou|mu|na|nai|nan|nang|nao|ne" .
                "|nei|nen|neng|ni|nian|niang|niao|nie|nin|ning|niu|nong|nu|nv|nuan|nue|nuo|o|ou|pa|pai|pan|pang|pao|pei|pen" .
                "|peng|pi|pian|piao|pie|pin|ping|po|pu|qi|qia|qian|qiang|qiao|qie|qin|qing|qiong|qiu|qu|quan|que|qun|ran|rang" .
                "|rao|re|ren|reng|ri|rong|rou|ru|ruan|rui|run|ruo|sa|sai|san|sang|sao|se|sen|seng|sha|shai|shan|shang|shao|" .
                "she|shen|sheng|shi|shou|shu|shua|shuai|shuan|shuang|shui|shun|shuo|si|song|sou|su|suan|sui|sun|suo|ta|tai|" .
                "tan|tang|tao|te|teng|ti|tian|tiao|tie|ting|tong|tou|tu|tuan|tui|tun|tuo|wa|wai|wan|wang|wei|wen|weng|wo|wu" .
                "|xi|xia|xian|xiang|xiao|xie|xin|xing|xiong|xiu|xu|xuan|xue|xun|ya|yan|yang|yao|ye|yi|yin|ying|yo|yong|you" .
                "|yu|yuan|yue|yun|za|zai|zan|zang|zao|ze|zei|zen|zeng|zha|zhai|zhan|zhang|zhao|zhe|zhen|zheng|zhi|zhong|" .
                "zhou|zhu|zhua|zhuai|zhuan|zhuang|zhui|zhun|zhuo|zi|zong|zou|zu|zuan|zui|zun|zuo";
    $_DataValue = "-20319|-20317|-20304|-20295|-20292|-20283|-20265|-20257|-20242|-20230|-20051|-20036|-20032|-20026|-20002|-19990" .
                  "|-19986|-19982|-19976|-19805|-19784|-19775|-19774|-19763|-19756|-19751|-19746|-19741|-19739|-19728|-19725" .
                  "|-19715|-19540|-19531|-19525|-19515|-19500|-19484|-19479|-19467|-19289|-19288|-19281|-19275|-19270|-19263" .
                  "|-19261|-19249|-19243|-19242|-19238|-19235|-19227|-19224|-19218|-19212|-19038|-19023|-19018|-19006|-19003" .
                  "|-18996|-18977|-18961|-18952|-18783|-18774|-18773|-18763|-18756|-18741|-18735|-18731|-18722|-18710|-18697" .
                  "|-18696|-18526|-18518|-18501|-18490|-18478|-18463|-18448|-18447|-18446|-18239|-18237|-18231|-18220|-18211" .
                  "|-18201|-18184|-18183|-18181|-18012|-17997|-17988|-17970|-17964|-17961|-17950|-17947|-17931|-17928|-17922" .
                  "|-17759|-17752|-17733|-17730|-17721|-17703|-17701|-17697|-17692|-17683|-17676|-17496|-17487|-17482|-17468" .
                  "|-17454|-17433|-17427|-17417|-17202|-17185|-16983|-16970|-16942|-16915|-16733|-16708|-16706|-16689|-16664" .
                  "|-16657|-16647|-16474|-16470|-16465|-16459|-16452|-16448|-16433|-16429|-16427|-16423|-16419|-16412|-16407" .
                  "|-16403|-16401|-16393|-16220|-16216|-16212|-16205|-16202|-16187|-16180|-16171|-16169|-16158|-16155|-15959" .
                  "|-15958|-15944|-15933|-15920|-15915|-15903|-15889|-15878|-15707|-15701|-15681|-15667|-15661|-15659|-15652" .
                  "|-15640|-15631|-15625|-15454|-15448|-15436|-15435|-15419|-15416|-15408|-15394|-15385|-15377|-15375|-15369" .
                  "|-15363|-15362|-15183|-15180|-15165|-15158|-15153|-15150|-15149|-15144|-15143|-15141|-15140|-15139|-15128" .
                  "|-15121|-15119|-15117|-15110|-15109|-14941|-14937|-14933|-14930|-14929|-14928|-14926|-14922|-14921|-14914" .
                  "|-14908|-14902|-14894|-14889|-14882|-14873|-14871|-14857|-14678|-14674|-14670|-14668|-14663|-14654|-14645" .
                  "|-14630|-14594|-14429|-14407|-14399|-14384|-14379|-14368|-14355|-14353|-14345|-14170|-14159|-14151|-14149" .
                  "|-14145|-14140|-14137|-14135|-14125|-14123|-14122|-14112|-14109|-14099|-14097|-14094|-14092|-14090|-14087" .
                  "|-14083|-13917|-13914|-13910|-13907|-13906|-13905|-13896|-13894|-13878|-13870|-13859|-13847|-13831|-13658" .
                  "|-13611|-13601|-13406|-13404|-13400|-13398|-13395|-13391|-13387|-13383|-13367|-13359|-13356|-13343|-13340" .
                  "|-13329|-13326|-13318|-13147|-13138|-13120|-13107|-13096|-13095|-13091|-13076|-13068|-13063|-13060|-12888" .
                  "|-12875|-12871|-12860|-12858|-12852|-12849|-12838|-12831|-12829|-12812|-12802|-12607|-12597|-12594|-12585" .
                  "|-12556|-12359|-12346|-12320|-12300|-12120|-12099|-12089|-12074|-12067|-12058|-12039|-11867|-11861|-11847" .
                  "|-11831|-11798|-11781|-11604|-11589|-11536|-11358|-11340|-11339|-11324|-11303|-11097|-11077|-11067|-11055" .
                  "|-11052|-11045|-11041|-11038|-11024|-11020|-11019|-11018|-11014|-10838|-10832|-10815|-10800|-10790|-10780" .
                  "|-10764|-10587|-10544|-10533|-10519|-10331|-10329|-10328|-10322|-10315|-10309|-10307|-10296|-10281|-10274" .
                  "|-10270|-10262|-10260|-10256|-10254";
    $_TDataKey = explode('|', $_DataKey);
    $_TDataValue = explode('|', $_DataValue);
    $_Data = array_combine($_TDataKey, $_TDataValue);
    arsort($_Data);
    reset($_Data);
    if ($_Code != 'gb2312') {
        $_String = _U2_Utf8_Gb($_String);
    }
    $_Res = '';
    for ($i = 0; $i < strlen($_String); $i++) {
        $_P = ord(substr($_String, $i, 1));
        if ($_P > 160) {
            $_Q = ord(substr($_String, ++$i, 1));
            $_P = $_P * 256 + $_Q - 65536;
        }
        $_Res .= _Pinyin($_P, $_Data);
    }
    return preg_replace("/[^a-z0-9]*/", '', $_Res);
}

function _Pinyin($_Num, $_Data) {
    if ($_Num > 0 && $_Num < 160) {
        return chr($_Num);
    } elseif ($_Num < -20319 || $_Num > -10247) {
        return '';
    } else {
        foreach ($_Data as $k => $v) {
            if ($v <= $_Num) {
                break;
            }
        }
        return $k;
    }
}

function _U2_Utf8_Gb($_C) {
    $_String = '';
    if ($_C < 0x80) {
        $_String .= $_C;
    } elseif ($_C < 0x800) {
        $_String .= chr(0xC0 | $_C >> 6);
        $_String .= chr(0x80 | $_C & 0x3F);
    } elseif ($_C < 0x10000) {
        $_String .= chr(0xE0 | $_C >> 12);
        $_String .= chr(0x80 | $_C >> 6 & 0x3F);
        $_String .= chr(0x80 | $_C & 0x3F);
    } elseif ($_C < 0x200000) {
        $_String .= chr(0xF0 | $_C >> 18);
        $_String .= chr(0x80 | $_C >> 12 & 0x3F);
        $_String .= chr(0x80 | $_C >> 6 & 0x3F);
        $_String .= chr(0x80 | $_C & 0x3F);
    }
    return iconv('UTF-8', 'GB2312', $_String);
}

/**
 * 是否在移动端上
 * @return boolean
 */
function is_on_mobile() {
    $agent = $_SERVER['HTTP_USER_AGENT'];
    if (preg_match("/(iPhone|iPod|Android|ios|iPad|mobile)/i", $agent)) {
        return TRUE;
    }

    return FALSE;
}

/**
 * 检测用户名
 * @param string 　字符
 * @param int 长度
 * @return bool 格式正确返回FALSE, 错误返回TRUE
 */
function check_username($str, $length = 6) {

    $str = trim($str);
    if (!preg_match('/^[\x{4e00}-\x{9fa5}\w\-]+$/u', $str)) {
        return true;
    }

    $len = $length * 2;
    $chars = $str;
    $c = $e = 0; //中文字个数 $c中文 $e 英文
    $str_len = strlen($chars); //一个字一个长度
    for ($i = 0; $i < $str_len; $i++) {
        if (preg_match('/[0-9a-zA-Z]/', $chars{$i})) {
            $e++;
        } else {
            $c++;
        }
    }
    $l = ceil($c / 3) * 2 + $e;
    if ($l > $len || $l < 2) {
        return true;
    }

    return false;
}

/**
 * 检测用户名
 * @param string 　字符
 * @param int 长度
 * @return bool 格式正确返回FALSE, 错误返回TRUE
 */
function check_title($str, $length = 30) {

    $str = trim($str);
    if (!preg_match('/^[\x{4e00}-\x{9fa5}\w\-\.\(\（\）\)]+$/u', $str)) {
        return true;
    }

    $len = $length * 2;
    $chars = $str;
    $c = $e = 0; //中文字个数 $c中文 $e 英文
    $str_len = strlen($chars); //一个字一个长度
    for ($i = 0; $i < $str_len; $i++) {
        if (preg_match('/[0-9a-zA-Z]/', $chars{$i})) {
            $e++;
        } else {
            $c++;
        }
    }
    $l = ceil($c / 3) * 2 + $e;
    if ($l > $len || $l < 2) {
        return true;
    }

    return false;
}

/**
 * 检测用户名
 * @param string 　字符
 * @param int 长度
 * @return bool 格式正确返回FALSE, 错误返回TRUE
 */
function check_password($str) {
    $pattern = '/^[\w]{6,100}$/u';
    if (preg_match($pattern, $str)) {
        return false;
    } else {
        return true;
    }
}

/**
 * 字符串防XSS攻击
 * @param string
 * @return string
 */
function remove_xss($val) {
    // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
    // this prevents some character re-spacing such as <java\0script>
    // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
    $val = preg_replace('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/', '', $val);

    // straight replacements, the user should never need these since they're normal characters
    // this prevents like <IMG SRC=@avascript:alert('XSS')>
    $search = 'abcdefghijklmnopqrstuvwxyz';
    $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $search .= '1234567890!@#$%^&*()';
    $search .= '~`";\,:?+/={}[]-_|\'\\';
    for ($i = 0; $i < strlen($search); $i++) {
        // ;? matches the ;, which is optional
        // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars

        // @ @ search for the hex values
        $val = preg_replace('/(&#[xX]0{0,8}' . dechex(ord($search[$i])) . ';?)/i', $search[$i], $val); // with a ;
        // @ @ 0{0,7} matches '0' zero to seven times
        $val = preg_replace('/(&#0{0,8}' . ord($search[$i]) . ';?)/', $search[$i], $val); // with a ;
    }

    // now the only remaining whitespace attacks are \t, \n, and \r
    //$ra1 = array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'base');
    $ra1 = array('javascript', 'vbscript', 'script', 'meta');
    $ra2 = array(
        'onabort',
        'onactivate',
        'onafterprint',
        'onafterupdate',
        'onbeforeactivate',
        'onbeforecopy',
        'onbeforecut',
        'onbeforedeactivate',
        'onbeforeeditfocus',
        'onbeforepaste',
        'onbeforeprint',
        'onbeforeunload',
        'onbeforeupdate',
        'onblur',
        'onbounce',
        'oncellchange',
        'onchange',
        'onclick',
        'oncontextmenu',
        'oncontrolselect',
        'oncopy',
        'oncut',
        'ondataavailable',
        'ondatasetchanged',
        'ondatasetcomplete',
        'ondblclick',
        'ondeactivate',
        'ondrag',
        'ondragend',
        'ondragenter',
        'ondragleave',
        'ondragover',
        'ondragstart',
        'ondrop',
        'onerror',
        'onerrorupdate',
        'onfilterchange',
        'onfinish',
        'onfocus',
        'onfocusin',
        'onfocusout',
        'onhelp',
        'onkeydown',
        'onkeypress',
        'onkeyup',
        'onlayoutcomplete',
        'onload',
        'onlosecapture',
        'onmousedown',
        'onmouseenter',
        'onmouseleave',
        'onmousemove',
        'onmouseout',
        'onmouseover',
        'onmouseup',
        'onmousewheel',
        'onmove',
        'onmoveend',
        'onmovestart',
        'onpaste',
        'onpropertychange',
        'onreadystatechange',
        'onreset',
        'onresize',
        'onresizeend',
        'onresizestart',
        'onrowenter',
        'onrowexit',
        'onrowsdelete',
        'onrowsinserted',
        'onscroll',
        'onselect',
        'onselectionchange',
        'onselectstart',
        'onstart',
        'onstop',
        'onsubmit',
        'onunload'
    );
    $ra = array_merge($ra1, $ra2);

    $found = true; // keep replacing as long as the previous round replaced something
    while ($found == true) {
        $val_before = $val;
        for ($i = 0; $i < sizeof($ra); $i++) {
            $pattern = '/';
            for ($j = 0; $j < strlen($ra[$i]); $j++) {
                if ($j > 0) {
                    $pattern .= '(';
                    $pattern .= '(&#[xX]0{0,8}([9ab]);)';
                    $pattern .= '|';
                    $pattern .= '|(&#0{0,8}([9|10|13]);)';
                    $pattern .= ')*';
                }
                $pattern .= $ra[$i][$j];
            }
            $pattern .= '/i';
            $replacement = substr($ra[$i], 0, 2) . '<x>' . substr($ra[$i], 2); // add in <> to nerf the tag
            $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
            if ($val_before == $val) {
                // no replacements were made, so exit the loop
                $found = false;
            }
        }
    }
    return $val;
}


/**
 * 过滤数据   转换类型,去XSS
 * @param mixed 要处理的数据
 */
function filter_data($data) {
    if (is_numeric($data)) {
        return (int)$data;
    }

    if (is_string($data)) {
        return remove_xss($data);
    }

    if (is_array($data)) {
        foreach ($data as $k => $v) {
            $data[$k] = filter_data($v);
        }
        return $data;
    }

    return $data;
}

/**
 * 时间格式是否正确
 * @param string $str
 * @return boolean
 */
function check_time($str) {
    $time_arr = explode(' ', $str);
    if (!isset($time_arr[0]) || !$time_arr[0]) {
        return false;
    }

    return is_date($time_arr[0]);
}

/**
 * 是否是时间格式
 */
function is_date($str, $format = "Y-m-d") {
    $strArr = explode("-", $str);
    if (empty($strArr)) {
        return false;
    }
    foreach ($strArr as $val) {
        if (strlen($val) < 2) {
            $val = "0" . $val;
        }
        $newArr[] = $val;
    }

    $str = implode("-", $newArr);
    $unixTime = strtotime($str);
    $checkDate = date($format, $unixTime);
    if ($checkDate == $str) {
        return true;
    } else {
        return false;
    }
}

/**
 * 取得某年某月的最后一天
 * @param int $year
 * @param int $month
 * @return number|string
 */
function get_last_month_day($year = 0, $month = 0) {
    if ($year == 0) {
        $year = date('Y');
    }
    if ($month == 0) {
        $month = date('n');
    }

    if ((!is_numeric($year) && strlen($year) != 4) || !is_numeric($month)) {
        return 0;
    }

    //return date('d', strtotime('-1 day', strtotime('+1 month')));

    if ($month == 12) {
        $year = $year + 1;
        $month = 1;
    } else {
        $month = $month + 1;
    }

    //return $year.'-'.$month;
    $t = mktime(1, 20, 0, $month, 1, $year);
    $t = $t - 60 * 60 * 24;

    return date('d', $t);
}

/**
 * 判断是否为空 去除<br></br><p></p>后判断
 * @param string 要判断的字符串
 * @param string 要保留的html标签
 */
function is_empty_string($string, $save_tags = '<img>') {
    $string = strip_tags($string, $save_tags);
    $string = str_replace(array('&nbsp;', '&NBSP;'), '', $string);
    $string = trim($string);
    if (empty($string)) {
        return true;
    }

    return false;
}

/**
 * 是否在微信浏览器中
 * @return boolean
 */
function is_weixin() {
    if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false) {
        return true;
    }

    return false;
}

/**
 * 接收请求数据封装
 * @param string $key 参数key
 * @param string $default 默认值
 * @param string $type 请求类型
 * @param int $do_filter 是否过滤
 * @return mixed
 */
function an_request($key, $default = '', $type = 'request', $do_filter = 1) {
    if ('get' == $type) {
        $value = Request::Get($key, $default);
    } else {
        if ('post' == $type) {
            $value = Request::Post($key, $default);
        } else {
            $value = Request::getParam($key, $default);
        }
    }

    if ($do_filter) {
        if (is_array($default) && is_array($value)) {
            foreach ($value as $k => $v) {
                $value[$k] = trim(AnFilter::filter_string($v));
            }
        } else {
            $value = trim(AnFilter::filter_string($value));
        }
    }

    return $value;
}

/**
 * curl
 * @param string $url
 * @param string $data
 * @param int $is_json 1:是json数据 0:非json
 * @param int $json_deep 1:需要json_decode时带上参数true 0:不需要带true
 * @return mixed
 */
function an_curl($url, $data = null, $is_json = 0, $json_deep = 0) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    if (!empty($data)) {
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($curl);
    curl_close($curl);

    if (1 == $is_json) {
        if ($json_deep) {
            $output = json_decode($output, true);
        } else {
            $output = json_decode($output);
        }
    }

    return $output;
}

/**
 * 取微博地址
 * @param int $weibo_id
 * @return string
 */
function generate_weibo_url($weibo_id) {
    return 'http://weibo.com/' . $weibo_id;
}

/**
 * 取微博详情页
 * @param int $weibo_id
 * @param string $mid
 * @return string
 */
function generate_weibo_detail_url($weibo_id, $mid) {
    $mid_str = midToStr($mid);
    return 'http://weibo.com/' . $weibo_id . '/' . $mid_str;
}

// 新浪微博
//转微博地址
function midToStr($mid) {
    settype($mid, 'string');
    $mid_length = strlen($mid);
    $url = '';
    $str = strrev($mid);
    $str = str_split($str, 7);

    foreach ($str as $v) {
        $char = intTo62(strrev($v));
        $char = str_pad($char, 4, "0");
        $url .= $char;
    }

    $url_str = strrev($url);

    return ltrim($url_str, '0');
}

/* url 10 进制 转62进制*/

function intTo62($int10) {
    $s62 = '';
    $r = 0;
    while ($int10 != 0) {
        $r = $int10 % 62;
        $s62 .= str62keys_int_62($r);
        $int10 = floor($int10 / 62);
    }

    return $s62;
}

function str62keys_int_62($key) //62进制字典
{
    $str62keys = array(
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "a",
        "b",
        "c",
        "d",
        "e",
        "f",
        "g",
        "h",
        "i",
        "j",
        "k",
        "l",
        "m",
        "n",
        "o",
        "p",
        "q",
        "r",
        "s",
        "t",
        "u",
        "v",
        "w",
        "x",
        "y",
        "z",
        "A",
        "B",
        "C",
        "D",
        "E",
        "F",
        "G",
        "H",
        "I",
        "J",
        "K",
        "L",
        "M",
        "N",
        "O",
        "P",
        "Q",
        "R",
        "S",
        "T",
        "U",
        "V",
        "W",
        "X",
        "Y",
        "Z"
    );
    return $str62keys[$key];
}

/**
 * 截取html文本，同时保留换行
 * @param string $html
 * @param int $len
 * @param string $replace
 * @return string
 * @author qianym@alltosun.com
 */
function strip_html($html, $len = 150, $fix = '...') {
    $replace = '。...';
    $returnHtml = str_replace('</p>', '<br>', $html);
    $returnHtml = strip_tags(str_replace(array('<br>', '<br/>', '<br />'), $replace, $returnHtml));
    $returnHtml = AnString::cutStr($returnHtml, $len, $fix);

    if (strlen($html) != strlen($returnHtml) && mb_strlen($html, 'utf-8') > $len) {
        $returnHtml .= $fix;
    }

    return AnString::stripEmptyLines(trim(str_replace($replace, '<br>', $returnHtml), '<br>'));
}

/**
 * 上传文件
 * @param $file_info
 * @param $res_name 生成缩略图
 * @param $is_attachment 是否插入附件表
 *
 */
function upload_file($file_info, $is_attachment = false, $res_name = '') {
    if (!ONDEV) {
        return aliysso_helper::upload_file($file_info, $is_attachment, $res_name);
    } else {
        return ondev_upload_file($file_info, $is_attachment, $res_name);
    }
}

function ondev_upload_file($file_info, $is_attachment = false, $res_name = '') {
    // php.ini限制的post大小
    $POST_MAX_SIZE = ini_get('post_max_size');
    $unit = strtoupper(substr($POST_MAX_SIZE, -1));
    $multiplier = ($unit == 'M' ? 1048576 : ($unit == 'K' ? 1024 : ($unit == 'G' ? 1073741824 : 1)));

    if ((int)$_SERVER['CONTENT_LENGTH'] > $multiplier * (int)$POST_MAX_SIZE && $POST_MAX_SIZE) {
        header("HTTP/1.1 500 Internal Server Error"); // This will trigger an uploadError event in SWFUpload
        throw new Exception('对不起，上传文件超过服务器限制大小。');
    }

    $allow_type = array_merge(Config::get('allow_image_type'), Config::get('allow_flash_type'));
    $upload_path = UPLOAD_PATH;

    // 上传验证
    $failed_msg = check_upload($file_info);
    if (!empty($failed_msg)) {
        throw new Exception($failed_msg);
    }

    // 上传
    $uploader = new Uploadr($upload_path, $allow_type);
    try {
        $file_path = $uploader->uploadFile($file_info['tmp_name']);
    } catch (Exception $e) {
        throw new Exception($e->getMessage());
    }

    if (empty($file_path)) {
        throw new Exception('图片保存失败，请重试');
    }

    if (!$is_attachment) {
        if ($res_name) {
            make_thumb($file_path, $res_name);
        }
        return $file_path;
    }

    // 插入数据库
    $attachment_id = 0;
    // $attachment_info = _model('file')->read(array('path'=>$file_path));
    if (1 != 1) {
        // 如果同一张图片在不同模型中使用，这样处理会导致返回的缩略图比例只是第1个模型产生的
        // 可采用解决方案：图片存放名称不用md5唯一值，改为当前时间+计数，已在Uploadr.php采用该方案
        $attachment_id = $attachment_info['id'];
    } else {
        // 附件类型
        $attachment_type = get_attachment_type($file_path);
        $attachment_info = array(
            'path' => $file_path,
            'user_id' => user_helper::get_user_id(),
            'type' => $attachment_type,
            'size' => $file_info['size'],
            'file_name' => htmlspecialchars($file_info['name'], ENT_NOQUOTES)
        );
        $attachment_id = _model('attachment')->create($attachment_info);

        // 缩略图
        // *requires res_name 前台上传工具必须传入res_name
        if ($attachment_type == 1) {
            make_thumb($file_path, $res_name);
        }
    }

    if (empty($attachment_id)) {
        throw new Exception('数据库插入失败，请重试');
    }
    return array('id' => $attachment_id, 'file_path' => $file_path);
}

/**
 * 获取后台当前操作的控制器和方法吗
 * @param string 如：user/admin/add
 */
function get_action_name() {
    $request_uri = $_SERVER['REQUEST_URI'];
    $preg = '/([a-zA-Z_-]+){0,1}\/admin(\/[a-zA-Z0-9_-]+){0,1}/';
    $preg_res = preg_match($preg, $request_uri, $preg_arr);
    if ($preg_res) {
        $curr_action_name = $preg_arr[0];

        if (empty($preg_arr[1])) {
            $curr_action_name = substr($curr_action_name, 1);
        }
        if ($preg_arr[2] == '/index') {
            $curr_action_name = substr($curr_action_name, 0, -6);
        }
    } else {
        return FALSE;
    }

    return $curr_action_name;
}

/**
 * 获取后台当前操作的模块名
 */
function get_module_name() {
    $url = AnUrl::getInstance();
    return $url['module'];
}

/**
 * 获取后台当前操作的方法名
 */
function get_action_title() {
    $url = AnUrl::getInstance();
    return $url['action'];
}

/**
 * 获取随机字符
 */
function random($length = 6, $numeric = 0) {
    PHP_VERSION < '4.2.0' && mt_srand((double)microtime() * 1000000);
    if ($numeric) {
        $hash = sprintf('%0' . $length . 'd', mt_rand(0, pow(10, $length) - 1));
    } else {
        $hash = '';
        $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789abcdefghjkmnpqrstuvwxyz';
        $max = strlen($chars) - 1;
        for ($i = 0; $i < $length; $i++) {
            $hash .= $chars[mt_rand(0, $max)];
        }
    }
    return $hash;
}

/**
 *获取客户端ip
 * @return string
 */
function get_ip() {
    $ip = '';
    if (getenv("HTTP_CLIENT_IP")) {
        $ip = getenv("HTTP_CLIENT_IP");
    } else {
        if (getenv("HTTP_X_FORWARDED_FOR")) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        } else {
            if (getenv("REMOTE_ADDR")) {
                $ip = getenv("REMOTE_ADDR");
            }
        }
    }

    return $ip;
}

/**
 * 跳转到登陆
 */

function checkLogin($return_url = '') {
    if (!$return_url) {
        $return_url = AnUrl('index'); // 返回地址
    }

    $user_id = user_helper::get_user_id();

    if (!$user_id) {
        //Response::redirect(AnUrl('user/login'));
        // liw 添加urlencode，避免参数被过滤
        Response::redirect(AnUrl('user/login?rfUrl=' . urlencode($return_url)));
        Response::flush();
        exit;
    }
}

/**
 * @param $a
 * @param $b
 * @return array
 */
function array_extend($a, $b) {
    if (function_exists('array_replace_recursive')) {
        return array_replace_recursive($a, $b);
    } else {
        foreach ($b as $k => $v) {
            if (is_array($v)) {
                if (!isset($a[$k])) {
                    $a[$k] = $v;
                } else {
                    $a[$k] = array_extend($a[$k], $v);
                }
            } else {
                $a[$k] = $v;
            }
        }
        return $a;
    }
}

/**
 * @param [... array]
 * @return array|null
 */
function parse_param() {
    $params = func_get_args();
    $len = count($params);
    if ($len <= 0) {
        return NULL;
    } else {
        if ($len == 1) {
            return $params[0];
        } else {
            $source = array_shift($params);
            foreach ($source as $k => $v) {
                if (is_array($v)) {
                    $dep = array($v);
                    for ($i = 0; $i < count($params); $i++) {
                        if (isset($params[$i][$k])) {
                            $dep[] = $params[$i][$k];
                        }
                    }
                    $source[$k] = call_user_func_array('parse_param', $dep);
                } else {
                    for ($i = count($params) - 1; $i >= 0; $i--) {
                        if (isset($params[$i][$k])) {
                            $source[$k] = $params[$i][$k];
                            break;
                        }
                    }
                }
            }
            return $source;
        }
    }
}

/**
 * enable dev filters
 *
 * @param $filter
 * @return mixed
 */
function enable_filter($filter) {
    $test = Request::getParam('test');
    if ((ONDEV || !empty($test)) && array_key_exists('is_enable', $filter)) {
        unset($filter['is_enable']);
    }
    return $filter;
}

/**
 * 返回ajax数据
 */
function return_data($flag, $message, $info = array(), $do_des = 1) {
    header('Content-type: application/json; charset=utf-8');

    $return_data = array(
        'flag' => $flag,
        'message' => $message,
    );

    if ($info) {
        $return_data['response'] = $info;
    }

    if ($do_des) {
        // 转成json数据
        $return_data = json_encode($return_data, JSON_BIGINT_AS_STRING | JSON_UNESCAPED_UNICODE);
    }

    exit($return_data);
}

/**
 * 将从数据库中取出的数据以以其中一个字段为键转化为新的数组
 *
 * @param $field
 * @param $data_list
 * @return array
 */
function array_to_filelds_assoc($field, $data_list) {
    if (!$data_list || !is_array($data_list)) {
        return array();
    }

    $list = array();
    foreach ($data_list as $k => $v) {
        if (!isset($v[$field])) {
            continue;
        }
        $list[$v[$field]] = $v;
    }
    return $list;
}

?>